package base.util;

import base.entity.regitem.RegItem;
import base.factory.Factory;
import base.factory.impl.RegItemFactory;


import java.io.File;

/**
 * RegItemUtils的工具类
 * @Author: x1aolone
 * @Date: 2019/9/27 14:57
 */
public class RegItemUtils {

    /**
     * 验证参数是否合法，合法返回true，不合法返回false
     * @param clazz 参数类型的class
     * @param field 参数对象
     * @param min 对number来说是最小值，对String来说是最小长度
     * @param max 对number来说是最大值，对String来说是最大长度
     * @return 参数合法返回true，不合法返回false
     */
    public static boolean fieldIsApproved (Class<?> clazz, Object field, int min, int max) {
        // 空指针判断
        if (field == null) {
            return false;
        } else {
            // 进行内容判断
            if (clazz.equals(String.class)) {
                // 如果是String类型的参数，getBytes()的长度需要为[min, max]
                int length = ((String)field).getBytes().length;
                if (min <= length && length <= max) {
                    return true;
                }
            } else if (clazz.equals(byte.class)) {
                // 如果是byte类型的参数，值需要为[min, max]
                if (min <= (byte)field && (byte)field <= max) {
                    return true;
                }
            }
        }
        StringBuilder error = new StringBuilder("String类型的参数的长度不满足要求，要求为")
                .append("[").append(min).append(", ").append(max).append("]");
        System.err.println(error);
        return false;
    }

    /**
     * 从disk.txt中读取一个byte[8]数组
     * @param skipFileBytesLength 从文件头跳过的字节数
     * @return FileRegistrationItem或者DirectoryRegistrationItem的子类对象
     */
    public static RegItem read (File file, int skipFileBytesLength) {
        Factory<RegItem> regItemFactory = RegItemFactory.getInstance();
        byte[] content = ByteFileIOUtils.read(file, 8, skipFileBytesLength);
        RegItem regItem;
        // 正常的目录登记项结构：3字节目录名+2字节空格+1字节目录属性+1字节起始盘块号+0
        // 正常的文件登记项结构：3字节文件名+2字节类型+1字节目录属性+1字节起始盘块号+1字节长度（不为0）
        // 填充的空白登记项结构：8字节的0
        boolean itemUseful = false;
        for (int i = 0; i < content.length; i++) {
            if (content[i] != 0) {
                // 只有全为0，itemUseful才为false，否则就是true，证明该登记项不是填充的内容
                itemUseful = true;
                break;
            }
        }
        if (itemUseful) {
            // 如果登记项不是填充的内容，而是真实有效的内容
            // 判断content[5]是不是1，如0000 1000，除8得0000 1，模2得1，此时为目录登记项
            if (content[5] /8 % 2 != 0) {
                regItem = regItemFactory.newDirInstance(content);
            } else {
                regItem = regItemFactory.newFileInstance(content);
            }
        } else {
            regItem = null;
        }
        return regItem;
    }

    /**
     * 把RegistrationItem的对象的内容变成byte[8]，写入disk.txt中
     * @param content 需要写入disk.txt的byte数组
     * @param skipFileBytesLength 从文件头跳过的字节数
     */
    public static void write (File file, byte[] content, int skipFileBytesLength) {
        ByteFileIOUtils.write(file, content, skipFileBytesLength);
        return;
    }

    /**
     * 把RegItem的对象写入disk.txt中
     * 如果为null写入DiskIOUtils.FILLED_8BYTES_ZERO_ARRAY
     * 如果不为null，写入对象.getBytes()
     * @param r 需要写入disk.txt的RegItem对象
     * @param skipFileBytesLength 从文件头跳过的字节数
     */
    public static void write (File file, RegItem r, int skipFileBytesLength) {
        if (r == null) {
            // 如果对象是null，证明这个登记项是填充的，那么写入的时候也写入填充物[0,0,0,0,0,0,0,0]
            ByteFileIOUtils.write(file, ByteFileIOUtils.FILLED_8BYTES_ZERO_ARRAY, skipFileBytesLength);
        } else {
            ByteFileIOUtils.write(file, r.getBytes(), skipFileBytesLength);
        }
    }


    /**
     * 工具类中不能有public或者default的构造方法
     * 同时抛出Error，防止通过反射创建工具类对象
     */
    private RegItemUtils () {
        throw new RuntimeException("请不要实例化工具类！");
    }




}
